#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    settings(QApplication::organizationName(), QApplication::applicationName())
{
    ui->setupUi(this);
    setFixedSize(400, 500);
    ui->lineEdit_port->setValidator(new QIntValidator(1024, 65535, this));
    ui->lineEdit_root_dir->setText(settings.value("Directory", QApplication::applicationDirPath()).toString());
    QAction *action_browser = new QAction;
    action_browser->setIcon(QIcon::fromTheme("folder"));
    ui->lineEdit_root_dir->addAction(action_browser, QLineEdit::TrailingPosition);
    connect(action_browser, &QAction::triggered, [=](){
        QString dir = QFileDialog::getExistingDirectory(this, tr("Root Directory"),
                                                        settings.value("Directory", QApplication::applicationDirPath()).toString(),
                                                        QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
        if (dir != "") {
            ui->lineEdit_root_dir->setText(dir);
            settings.setValue("Directory", ui->lineEdit_root_dir->text());
        }
    });

    QList<QNetworkInterface> list = QNetworkInterface::allInterfaces();
    foreach (QNetworkInterface interface, list) {
        QList<QNetworkAddressEntry> entryList = interface.addressEntries();
        foreach (QNetworkAddressEntry entry, entryList) {
            if (!entry.ip().toString().contains("::") && entry.ip().toString() != "127.0.0.1") {
                IP = entry.ip().toString();
                ui->lineEdit_ip->setText(IP);
            }
        }
    }

    connect(ui->pushButton_start, &QPushButton::toggled, [=](bool b){       
        if (b) {
            state = 0;
            port_local = 9999;
            while (!tcpServer->listen(QHostAddress::Any, port_local)) {
                port_local--;
            }
            ui->label_local->setText(IP + ":" + QString::number(port_local));
            ui->lineEdit_port->setText(QString::number(port_local));
            ui->textBrowser->clear();
            ui->textBrowser->append("[" + QDateTime::currentDateTime().toString("HH:mm:ss") + "] 监听：" + IP + ":" + QString::number(port_local));
            ui->pushButton_start->setText("Stop");
        } else {
            tcpServer->close();
            ui->pushButton_start->setText("Start");
        }
    });

    connect(ui->pushButton_add, &QPushButton::clicked, [=]{
        if (path == "")
            path = ".";
        QStringList SL_path = QFileDialog::getOpenFileNames(this, "上传文件", path);
        //qDebug() << SL_path;        
        for (int i=0; i<SL_path.length(); i++) {            
            QString filepath = SL_path.at(i);
            path = filepath;
            //qDebug() << filepath;
            upload(filepath);
        }
    });

    connect(ui->pushButton_clear, &QPushButton::clicked, [=]{
        ui->textBrowser->clear();
    });

    tcpServer = new QTcpServer(this);
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newConnect()));
    ui->pushButton_start->toggle();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::newConnect()
{    
    tcpSocket = tcpServer->nextPendingConnection();
    ui->textBrowser->append("[" + QDateTime::currentDateTime().toString("HH:mm:ss") + "] " + tcpSocket->peerAddress().toString().replace("::ffff:","") + ":" + QString::number(tcpSocket->peerPort()));
    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readyRead()));

    connect(tcpSocket, &QTcpSocket::disconnected, [=](){
        qDebug() << state;
        if (state == 0) {
            state = 1;
        } else {
            file.close();            
            file.open(QIODevice::ReadOnly);
            qDebug() << "setFileTime" << file.setFileTime(QDateTime::fromTime_t(lastModified), QFileDevice::FileModificationTime);
            file.close();
            state = 0;
            length = 0;
        }
    });

    connect(tcpSocket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), [=](QAbstractSocket::SocketError socketError){
        qDebug() << socketError;
        QMetaEnum metaEnum = QMetaEnum::fromType<QAbstractSocket::SocketError>();
        QString errorString = metaEnum.valueToKey(socketError);
        ui->textBrowser->append("[" + QDateTime::currentDateTime().toString("HH:mm:ss") + "] " + errorString);
    });
}

void MainWindow::readyRead()
{
    QByteArray BA = tcpSocket->readAll();
    //qDebug() << BA ;    
    if (state == 0) {
        QString s = BA;
        QJsonParseError JPE;
        QJsonDocument JD = QJsonDocument::fromJson(s.toUtf8(), &JPE);
        QString fileName = "?";
        if (JPE.error == QJsonParseError::NoError) {
            if (JD.isObject()) {
                QJsonObject JO = JD.object();
                fileName = JO.value("fileName").toString();
                lastModified = JO.value("lastModified").toDouble()/1000;
            }
        }
        ui->textBrowser->append("[" + QDateTime::currentDateTime().toString("HH:mm:ss") + "] " + "接收：" + fileName);
        QString filepath = ui->lineEdit_root_dir->text() + "/" + fileName;
        file.setFileName(filepath);
        file.open(QIODevice::WriteOnly);
    } else {
        file.write(BA);        
        length += BA.length();
        ui->statusBar->showMessage("接收：" + BS(length));
    }
}

QString MainWindow::BS(long b)
{
    QString s = "";
    if (b > 999999999) {
        s = QString::number(b/(1024*1024*1024.0), 'f', 2) + " GB";
    } else {
        if (b > 999999) {
            s = QString::number(b/(1024*1024.0), 'f', 2) + " MB";
        } else {
            if (b > 999) {
                s = QString::number(b/(1024.0), 'f', 2) + " KB";
            } else {
                s = QString::number(b) + " B";
            }
        }
    }
    return s;
}

void MainWindow::upload(QString filepath)
{
    if (ui->lineEdit_ip->text() == IP) {
        ui->statusBar->showMessage("不需要上传给自己！");
        return;
    }
    qint64 port = ui->lineEdit_port->text().toInt();
    QTcpSocket *tcpSocket1 = new QTcpSocket(this);
    connect(tcpSocket1, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), [=](QAbstractSocket::SocketError socketError){
        qDebug() << socketError;
        QMetaEnum metaEnum = QMetaEnum::fromType<QAbstractSocket::SocketError>();
        QString errorString = metaEnum.valueToKey(socketError);
        ui->textBrowser->append("[" + QDateTime::currentDateTime().toString("HH:mm:ss") + "] " + errorString);
    });

    tcpSocket1->connectToHost(QHostAddress(ui->lineEdit_ip->text()), port);
    connect(tcpSocket1, &QTcpSocket::connected, [=](){
        QString fileName = QFileInfo(filepath).fileName();
        QJsonObject JO;
        JO.insert("fileName", fileName);
        JO.insert("lastModified", static_cast<qint64>(QFileInfo(filepath).lastModified().toTime_t())*1000);
        QString s = QJsonDocument(JO).toJson(QJsonDocument::Compact);
        tcpSocket1->write(s.toUtf8());
        tcpSocket1->close();
        ui->textBrowser->append("[" + QDateTime::currentDateTime().toString("HH:mm:ss") + "] 上传：" + s);
    });

    QTcpSocket *tcpSocket2 = new QTcpSocket(this);
    connect(tcpSocket2, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), [=](QAbstractSocket::SocketError socketError){
        qDebug() << socketError;
        QMetaEnum metaEnum = QMetaEnum::fromType<QAbstractSocket::SocketError>();
        QString errorString = metaEnum.valueToKey(socketError);
        ui->textBrowser->append("[" + QDateTime::currentDateTime().toString("HH:mm:ss") + "] " + errorString);
    });
    tcpSocket2->connectToHost(QHostAddress(ui->lineEdit_ip->text()), port);
    connect(tcpSocket2, &QTcpSocket::connected, [=](){
        qint64 length1 = 0;
        QFile file(filepath);
        if (file.open(QIODevice::ReadOnly)) {
            while (!file.atEnd()) {
                QByteArray BA = file.read(10240);  //每次读取10k数据
                tcpSocket2->write(BA);
                //qDebug() << "\b" << file.pos();
                length1 += 10240;
                ui->statusBar->showMessage("上传：" + BS(length1) + "/" + BS(file.size()));
            }
            ui->textBrowser->append("[" + QDateTime::currentDateTime().toString("HH:mm:ss") + "] " + "上传完成");
            tcpSocket2->close();
        }
    });
}

void MainWindow::dragEnterEvent(QDragEnterEvent *e)
{
    //if(e->mimeData()->hasFormat("text/uri-list")) //只接收文件列表
    e->acceptProposedAction(); //可以在这个窗口部件上拖放对象
}

void MainWindow::dropEvent(QDropEvent *e) //释放对方时，执行的操作
{
    QList<QUrl> urls = e->mimeData()->urls();
    qDebug() << urls << urls.size();
    if (urls.isEmpty())
        return;

    foreach (QUrl url, urls) {
        qDebug() << url.toString();
        QString filepath = url.toLocalFile();
        qDebug() << filepath;
        upload(filepath);
    }
}